package com.uinnova.product.eam.workable.listener;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.uinnova.product.eam.workable.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 流程结束推送工作台消息监听器
 */
@Slf4j
@Component("pushPlanNoticeListener")
public class PushPlanNoticeListener implements ExecutionListener {

    /**
     * 新网it视图审批
     */
    private static final String XW_IT_DIAGRAM_APPROVE = "xw_it_diagram_approve";
    /**
     * 新网模型资产审批
     */
    private static final String XW_MODEL_APPROVE = "xw_model_approve";
    /**
     * 业务方案审批
     */
    private static final String XW_BUSINESS_SCENARIO_APPROVE = "xw_business_scenario_approve";
    /**
     * 业务方案-子流程模型审批结束节点标识
     */
    private static final String XW_BUSINESS_SCENARIO_CHILD_MODEL_APPROVE = "child_model";
    /**
     * 国投架构评审
     */
    private static final String GT_TECHNICAL_SCHEME_APPROVE = "guotou_technical_scheme_approve_with_sub";

    /**
     * 国投视图评审流程定义key
     */
    public static final String GT_DIAGRAM_APPROVE = "guotou_diagram_approve";

    /**
     * 国投资产评审流程定义key
     */
    public static final String GT_ASSERT_APPROVE = "guotou_assert_approve";

    @Value("${eam.push.plan.notice}")
    private String eamPushPlanNoticeUrl;

    @Autowired
    private transient RuntimeService runtimeService;
    @Resource
    private transient HttpUtil httpUtil;
    @Autowired
    private transient HistoryService historyService;

    @Override
    public void notify(DelegateExecution execution) {
        String processInstanceId = execution.getProcessInstanceId();
        //当前流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        //获取历史任务
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByHistoricTaskInstanceEndTime()
                .asc()
                .list();
        //上一任务
        HistoricTaskInstance h =null;
        for (HistoricTaskInstance historicTaskInstance : historicTaskInstanceList) {
            if(historicTaskInstance.getEndTime()!=null&&historicTaskInstance.getDeleteReason() ==null){
                h= historicTaskInstance;
                break;
            }
        }
        if(h==null){
            h = historicTaskInstanceList.get(0);
        }

        log.info("上一任务：{}", JSONObject.toJSONString(h));
        List<HistoricVariableInstance> historicVariableInstanceList = historyService.createHistoricVariableInstanceQuery()
                .processInstanceId(processInstanceId)
                .taskId(h.getId()).list();
        //获取上一个节点执行结果
        Map<String, Object> variables = historicVariableInstanceList.stream()
                .filter(v -> !StringUtils.isEmpty(v.getVariableName()))
                .filter(v -> v.getValue() != null)
                .collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));
        log.info("变量：{}", JSONObject.toJSONString(variables));
        //会签节点
        Object finalResult = variables.get("goOut");
        if (finalResult == null) {
            //单节点
            finalResult = variables.get("pass");
        }
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(execution.getProcessInstanceId())
                .singleResult();
        String processDefinitionKey = historicProcessInstance.getProcessDefinitionKey();
        String taskDefinitionId = execution.getCurrentFlowElement().getDocumentation();

        log.info("processDefinitionKey:{},taskDefinitionId:{}", processDefinitionKey, taskDefinitionId);

        Map<String, String> params = new ConcurrentHashMap<>();
        if (variables.get("childVariable") != null) {
            JSONObject childVariable = JSON.parseObject(variables.get("childVariable").toString());
            Long countersignId = childVariable.getLong("countersignId");
            log.info("countersignId:{}", variables.get("countersignId"));
            if (countersignId != null) {
                params.put("countersignId", countersignId.toString());
            }
        }
        params.put("result", finalResult.toString());
        String opUser = variables.get("user") + "";
        log.info("opUser:{}", opUser);
        params.put("opUser", opUser);
        params.put("instanceName", historicProcessInstance.getName());
        String sourceType = "plan";
        if (isDiagram(processDefinitionKey)) {
            sourceType = "diagram";
        } else if (GT_TECHNICAL_SCHEME_APPROVE.equals(processDefinitionKey)){
            sourceType = "archReview";
        } else if (GT_ASSERT_APPROVE.equals(processDefinitionKey)){
            sourceType = "assert";
        } else if (isModel(processDefinitionKey, taskDefinitionId)) {
            sourceType = "model";
        }
        params.put("sourceType", sourceType);
        String sourceId = processInstance.getBusinessKey();
        //业务方案-子流程模型审批需要从环境变量取
        if (isBusinessPlanModel(processDefinitionKey, taskDefinitionId)) {
            String childVariable = variables.get("childVariable").toString();
            JSONObject jsonObject = JSON.parseObject(childVariable);
            sourceId = jsonObject.getString("childBusinessKey");
        }
        params.put("sourceId", sourceId);
        HistoricProcessInstance hi = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(execution.getProcessInstanceId())
                .singleResult();
        String startUserId = hi.getStartUserId();
        log.info("流程发起人[startUserId:{}]", startUserId);
        params.put("startUserId", startUserId);
        String paramsJson = JSON.toJSONString(params);
        log.info("推送工作台审批消息:{}", paramsJson);
        httpUtil.post(eamPushPlanNoticeUrl, params, Object.class);
    }

    /**
     * 是否新网it视图审批
     * @param processDefinitionKey 流程定义信息
     * @return
     */
    private Boolean isDiagram(String processDefinitionKey) {
        return XW_IT_DIAGRAM_APPROVE.equals(processDefinitionKey) || GT_DIAGRAM_APPROVE.equals(processDefinitionKey);
    }

    /**
     * 是否模型审批
     * @param processDefinitionKey 流程定义信息
     * @param taskDefinitionId 任务节点定义信息
     * @return
     */
    private Boolean isModel(String processDefinitionKey, String taskDefinitionId) {
        //新网模型资产审批
        if (XW_MODEL_APPROVE.equals(processDefinitionKey)) {
            return true;
        }
        //业务方案审批流程-模型资产审批
        return isBusinessPlanModel(processDefinitionKey, taskDefinitionId);
    }

    private Boolean isBusinessPlanModel(String processDefinitionKey, String taskDefinitionId) {
        return XW_BUSINESS_SCENARIO_APPROVE.equals(processDefinitionKey) &&
                XW_BUSINESS_SCENARIO_CHILD_MODEL_APPROVE.equals(taskDefinitionId);
    }
}
